/*
 * Copyright (c) 2019-2020, https://api.iot.10086.cn/(https://gitee.com/cmcc-iot-api/iot-card-open-application/).
 */
package cn.iot.card.open.ec.service;

import cn.iot.card.open.constants.Constants;
import cn.iot.card.open.constants.ErrorCode;
import cn.iot.card.open.constants.UrlConstants;
import cn.iot.card.open.ec.dto.ResponseDto;
import cn.iot.card.open.ec.dto.groupinfo.*;
import cn.iot.card.open.ec.warpper.EcGroupOfferingsWrapper;
import cn.iot.card.open.ec.warpper.EcGroupVoiceWhiteWrapper;
import cn.iot.card.open.exception.enums.BizExceptionEnum;
import cn.iot.card.open.modular.model.ResultDTO;
import cn.iot.card.open.modular.token.TokenService;
import cn.iot.card.open.pojo.page.LayuiPageFactory;
import cn.iot.card.open.pojo.page.LayuiPageInfo;
import cn.iot.card.open.util.ApiRequestUtil;
import cn.iot.card.open.util.CommonUtil;
import cn.iot.card.open.util.JsonUtil;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * 集团群组信息
 *
 * @author cmcc-iot-api
 * @date 20191231 14:54:38
 */
@Service
@Slf4j
public class EcGroupService {

    /**
     * 是否是最后一页
     */
    private static final String LASTPAGEFLAG = "N";

    /**
     * 上一次的页码
     */
    private long prePage = 1;

    /**
     * 上一次的总数
     */
    private long preTotal = 0;

    /**
     * 上一次的页条数
     */
    private long preSize = 0;

    @Autowired
    private ApiRequestUtil apiRequestUtil;

    @Autowired
    private TokenService tokenService;

    /**
     * 根据条件调用API接口查询集团群组信息
     *
     * @param transId
     * @param accountId
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200109 10:29:47
     */
    public LayuiPageInfo selectEcGroupInfo(String transId, String accountId) throws IOException {
        Page page = LayuiPageFactory.defaultPage();
        if (StringUtils.isBlank(accountId)) {
            log.info("[{}] query EcGroupInfo error，accountId is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        String startNum = String.valueOf(page.getCurrent());
        String pageSize = String.valueOf(page.getSize());
        parameterMap.put(Constants.REQUEST_PARAM_STARTNUM, startNum);
        parameterMap.put(Constants.REQUEST_PARAM_PAGESIZE, pageSize);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_INFO);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of querying EcGroupInfo is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_INFO);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query EcGroupInfo result string is {}.", transId, responseStr);
        ResponseDto<EcGroupDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupDTO>>() {});
        code = result.getStatus();
        // 如果api接口返回失败，则返回失败原因
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            log.warn("[{}] query EcGroupInfo error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        // 组装页面信息
        List<EcGroupDTO> groupVoices = result.getResult();
        if (ToolUtil.isEmpty(groupVoices)) {
            log.warn("[{}] query EcGroupInfo end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        String total = groupVoices.get(0).getTotalCount();
        List<EcGroupListDTO> groupList = groupVoices.get(0).getGroupList();
        String groupListStr = JsonUtil.toJson(groupList);
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        page.setTotal(Long.valueOf(total));
        page.setRecords(groupListMaps);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调用API接口实时查询集团群组本月套餐内流量共享/流量池使用情况（KB）.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200107 10:32:47
     */
    public LayuiPageInfo getShareUseAmount(String transId, String accountId, String groupId) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] query ShareUseAmount error, accountId or groupId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11048);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_DATA_MARGIN);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of query ShareUseAmount is invalid and start to get a new token.", transId, accountId);
            // 如果此处响应失败即为获取token失败，返回失败原因
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_DATA_MARGIN);
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query ShareUseAmount result string is {}.", transId, responseStr);
        ResponseDto<EcMarginByGroupDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcMarginByGroupDTO>>() {});
        code = result.getStatus();
        // 如果api接口返回失败，则返回失败原因
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 请求失败
            log.warn("[{}] query ShareUseAmount error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        // 组装页面信息
        List<EcMarginByGroupDTO> groupVoices = result.getResult();
        if (ToolUtil.isEmpty(groupVoices)) {
            log.warn("[{}] query ShareUseAmount end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }

        Page page = LayuiPageFactory.defaultPage();
        String groupListStr = "";

        // 流量池类型
        List<FlowPoolInfoDTO> flowPoolInfoList = groupVoices.get(0).getFlowPoolInfo();
        // 流量池共享类型
        List<FlowPoolSharingInfoDTO> flowPoolInfoDTOList = groupVoices.get(0).getFlowPoolSharingInfo();

        List<EcGroupFlowPoolRspDTO> ecGroupFlowPoolRspDTOList = new ArrayList<>();
        if (ToolUtil.isNotEmpty(flowPoolInfoList)) {
            for (FlowPoolInfoDTO flowPoolInfoDTO : flowPoolInfoList) {
                EcGroupFlowPoolRspDTO ecGroupFlowPoolRspDTO = new EcGroupFlowPoolRspDTO();
                ecGroupFlowPoolRspDTO.setUseAmount1(flowPoolInfoDTO.getUseAmount());
                ecGroupFlowPoolRspDTOList.add(ecGroupFlowPoolRspDTO);
            }
            groupListStr = JsonUtil.toJson(ecGroupFlowPoolRspDTOList);

        } else if (ToolUtil.isNotEmpty(flowPoolInfoDTOList)) {
            for (FlowPoolSharingInfoDTO flowPoolInfoDTO : flowPoolInfoDTOList) {
                EcGroupFlowPoolRspDTO ecGroupFlowPoolRspDTO = new EcGroupFlowPoolRspDTO();
                ecGroupFlowPoolRspDTO.setUseAmount1(flowPoolInfoDTO.getUseAmount());
                ecGroupFlowPoolRspDTO.setTotalAmount1(flowPoolInfoDTO.getTotalAmount());
                ecGroupFlowPoolRspDTO.setRemainAmount1(flowPoolInfoDTO.getRemainAmount());
                ecGroupFlowPoolRspDTOList.add(ecGroupFlowPoolRspDTO);
            }
            groupListStr = JsonUtil.toJson(ecGroupFlowPoolRspDTOList);
        }

        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        page.setTotal(ecGroupFlowPoolRspDTOList.size());
        page.setRecords(groupListMaps);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调用api接口查询集团群组本月累计GPRS使用量（KB）.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200107 10:32:47
     */
    public LayuiPageInfo getGprsUseAmount(String transId, String accountId, String groupId) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] get GprsUseAmount error, accountId or groupId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11048);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_DATA_USAGE);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of getGprsUseAmount is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_DATA_USAGE);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query GprsUseAmount result string is {}.", transId, responseStr);
        ResponseDto<EcUsageByGroupDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcUsageByGroupDTO>>() {});
        code = result.getStatus();
        // 如果api接口返回失败，则返回失败原因
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            log.warn("[{}] query GprsUseAmount error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<EcUsageByGroupDTO> ecUsageByGroupDTOList = result.getResult();
        if (ToolUtil.isEmpty(ecUsageByGroupDTOList)) {
            log.warn("[{}] query GprsUseAmount end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }

        List<EcGroupFlowPoolRspDTO> ecGroupFlowPoolRspDTOList = new ArrayList<>();
        for (EcUsageByGroupDTO ecUsageByGroupDTO : ecUsageByGroupDTOList) {
            EcGroupFlowPoolRspDTO ecGroupFlowPoolRspDTO = new EcGroupFlowPoolRspDTO();
            ecGroupFlowPoolRspDTO.setUseAmount(ecUsageByGroupDTO.getUseAmount());
            ecGroupFlowPoolRspDTOList.add(ecGroupFlowPoolRspDTO);
        }
        String groupListStr = JsonUtil.toJson(ecGroupFlowPoolRspDTOList);

        Page page = LayuiPageFactory.defaultPage();
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        page.setTotal(ecGroupFlowPoolRspDTOList.size());
        page.setRecords(groupListMaps);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调用api接口 查询 集团群组成员信息列表.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @param msisdn 卡号
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200116 11:11:21
     */
    public LayuiPageInfo getGroupMembers(String transId, String accountId, String groupId, String msisdn) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] get GroupMembers error, accountId or groupId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11048);
        }
        Page page = LayuiPageFactory.defaultPage();
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        String startNum = String.valueOf(page.getCurrent());
        String pageSize = String.valueOf(page.getSize());
        parameterMap.put(Constants.REQUEST_PARAM_STARTNUM, startNum);
        parameterMap.put(Constants.REQUEST_PARAM_PAGESIZE, pageSize);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_MEMBER);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of getGroupMembers is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_MEMBER);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query GroupMembers result string is {}.", transId, responseStr);
        ResponseDto<EcGroupMemberDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupMemberDTO>>() {});
        code = result.getStatus();
        // 如果api接口返回失败，则返回失败原因
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            log.warn("[{}] query GroupMembers error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<EcGroupMemberDTO> ecGroupMemberDTOList = result.getResult();
        if (ToolUtil.isEmpty(ecGroupMemberDTOList)) {
            log.warn("[{}] query GroupMembers end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        List<EcGroupMemberInfo> ecGroupMemberInfoList = ecGroupMemberDTOList.get(0).getMemberinfoList();
        page.setTotal(Long.valueOf(ecGroupMemberDTOList.get(0).getTotalCount()));
        if (ToolUtil.isNotEmpty(msisdn)){
            Iterator<EcGroupMemberInfo> iterator = ecGroupMemberInfoList.iterator();
            while (iterator.hasNext()) {
                EcGroupMemberInfo ecGroupMemberInfo = iterator.next();
                if (!ecGroupMemberInfo.getMemberNum().equals(msisdn)) {
                    iterator.remove();
                }
            }
            page.setTotal(ecGroupMemberInfoList.size());
        }
        String groupListStr = JsonUtil.toJson(ecGroupMemberInfoList);
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});

        page.setRecords(groupListMaps);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调用api接口实现集团群组成员管理.
     *
     * @param transId
     * @param ecGroupMemberReqDTO 待管理的成员信息
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200116 11:11:21
     */
    public ResponseData addOrDeleteGroupMember(String transId, EcGroupMemberReqDTO ecGroupMemberReqDTO) throws IOException {
        String groupId = ecGroupMemberReqDTO.getGroupId();
        String accountId = ecGroupMemberReqDTO.getAccountId();
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] addOrDeleteGroupMember error, accountId or groupId is null.", transId);
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_MSISDN, ecGroupMemberReqDTO.getMsisdn());
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        parameterMap.put(Constants.REQUEST_PARAM_OPERTYPE, ecGroupMemberReqDTO.getOperType());
        parameterMap.put(Constants.REQUEST_PARAM_EFFECTTYPE, ecGroupMemberReqDTO.getEffectType());
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.MANAGE_GROUP_MANAGMENT);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return getResponseData(tokenResultDTO.getCode());
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.MANAGE_GROUP_MANAGMENT);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                return getResponseData(tokenResultDTO.getCode());
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] add or delete GroupMember result string is {}.", transId, responseStr);
        // 组装页面信息
        ResponseDto<EcGroupMemberManageDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupMemberManageDTO>>() {});
        code = result.getStatus();
        if (ErrorCode.SUCCESS.getCode().equals(code)) {
            return ResponseData.success(JsonUtil.toJson(result.getResult()));
        } else {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] add or delete GroupMember error,error message is {}.", transId, result.getMessage());
            ResponseData responseData = new ResponseData();
            responseData.setCode(Integer.valueOf(code));
            responseData.setMessage(result.getMessage());
            return responseData;
        }
    }

    /**
     * 调用api接口实现群组成员流量限额设置.
     *
     * @param transId
     * @param ecGroupMemberSetFlowReqDTO 群组成员流量限额设置对象
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200117 15:35:44
     */
    public ResponseData setGroupMemberFlow(String transId, EcGroupMemberSetFlowReqDTO ecGroupMemberSetFlowReqDTO)
            throws IOException {
        String groupId = ecGroupMemberSetFlowReqDTO.getGroupId();
        String accountId = ecGroupMemberSetFlowReqDTO.getAccountId();
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] setGroupMemberFlow error accountId or groupId is null.", transId);
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_MSISDN, ecGroupMemberSetFlowReqDTO.getMsisdn());
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        parameterMap.put(Constants.REQUEST_PARAM_OPERTYPE, ecGroupMemberSetFlowReqDTO.getOperType());
        parameterMap.put(Constants.REQUEST_PARAM_OFFERID, ecGroupMemberSetFlowReqDTO.getOfferId());
        parameterMap.put(Constants.REQUEST_PARAM_APNNAME, ecGroupMemberSetFlowReqDTO.getApnName());
        parameterMap.put(Constants.REQUEST_PARAM_LIMITVALUE, ecGroupMemberSetFlowReqDTO.getOfferId());
        parameterMap.put(Constants.REQUEST_PARAM_ACTIONRULE, ecGroupMemberSetFlowReqDTO.getActionRule());
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.LIMIT_GROUP_MEMBER_DATA_USAGE);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return getResponseData(tokenResultDTO.getCode());
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.LIMIT_GROUP_MEMBER_DATA_USAGE);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                return getResponseData(tokenResultDTO.getCode());
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] set GroupMember Flow result string is {}.", transId, responseStr);
        // 组装页面信息
        ResponseDto<EcGroupMemberManageDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupMemberManageDTO>>() {});
        code = result.getStatus();
        if (ErrorCode.SUCCESS.getCode().equals(code)) {
            return ResponseData.success(JsonUtil.toJson(result.getResult()));
        } else {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] set GroupMember Flow error,error message is {}.", transId, result.getMessage());
            ResponseData responseData = new ResponseData();
            responseData.setCode(Integer.valueOf(code));
            responseData.setMessage(result.getMessage());
            return responseData;
        }
    }

    /**
     * 调用api接口 获取群组已订购资费列表.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @return 返回
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200117 16:14:19
     */
    public LayuiPageInfo getGroupOrders(String transId, String accountId, String groupId) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] query GroupOrders error, accountId or groupId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11048);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        parameterMap.put(Constants.REQUEST_QUERY_TYPE, "2");
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_ORDERED_OFFERINGS);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_ORDERED_OFFERINGS);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] get GroupOrders result string is {}.", transId, responseStr);
        ResponseDto<EcGroupOfferingDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupOfferingDTO>>() {});
        code = result.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] get GroupOrders error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<EcGroupOfferingDTO> groupVoices = result.getResult();
        if (ToolUtil.isEmpty(groupVoices)) {
            log.warn("[{}] get GroupOrders end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        List<EcGroupOfferingInfo> groupList = groupVoices.get(0).getOfferingInfoList();
        String groupListStr = JsonUtil.toJson(groupList);
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        Page page = LayuiPageFactory.defaultPage();
        page.setTotal(groupList.size());
        page.setRecords(groupListMaps);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 群组可变更资费列表.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @param offeringId 资费id
     * @return 返回 changeable offerings
     * @author cmcc-iot-api
     * @date 20200119 09:13:11
     */
    public LayuiPageInfo getChangeableOfferings(String transId, String accountId, String groupId, String offeringId) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId) || StringUtils.isBlank(offeringId)) {
            log.warn("[{}] getChangeableOfferings error, accountId or groupId or offeringId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11049);
        }
        // 封装调用api接口的参数
        Page page = LayuiPageFactory.defaultPage();
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        parameterMap.put(Constants.REQUEST_QUERY_TYPE, "1");
        parameterMap.put(Constants.REQUEST_PARAM_DESCOFFERINGID, offeringId);
        String startNum = String.valueOf(page.getCurrent());
        String pageSize = String.valueOf(page.getSize());
        parameterMap.put(Constants.REQUEST_PARAM_STARTNUM, startNum);
        parameterMap.put(Constants.REQUEST_PARAM_PAGESIZE, pageSize);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_CHANGEABLE_OFFERINGS);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of getChangeableOfferings is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_CHANGEABLE_OFFERINGS);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] get ChangeableOfferings result string is {}.", transId, responseStr);
        ResponseDto<EcGroupOrderChangeableDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupOrderChangeableDTO>>() {});
        code = result.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] get ChangeableOfferings error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<EcGroupOrderChangeableDTO> groupVoices = result.getResult();
        if (ToolUtil.isEmpty(groupVoices)) {
            log.warn("[{}] get ChangeableOfferings end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        EcGroupOrderChangeableDTO ecGroupOrderChangeableDTO = groupVoices.get(0);
        List<EcGroupOrderChangeableInfo> groupList = ecGroupOrderChangeableDTO.getOfferingInfoList();
        String groupListStr = JsonUtil.toJson(groupList);
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        // 后一页
        if (page.getCurrent() > prePage) {
            if (LASTPAGEFLAG.equals(ecGroupOrderChangeableDTO.getFlag())) {
                // 如果不是最后一页，设置总数超过当前数，点亮下一页按钮
                preTotal = preSize * page.getCurrent();
                page.setTotal(preTotal + 1);
            } else {
                preTotal = groupListMaps.size() + preSize * prePage;
                page.setTotal(preTotal);
            }
        } else if (page.getCurrent() == 1){
            // 第一页
            preSize = groupListMaps.size();
            if (LASTPAGEFLAG.equals(ecGroupOrderChangeableDTO.getFlag())) {
                // 如果不是最后一页，设置总数超过当前数，点亮下一页按钮
                page.setTotal(preSize + 1);
            } else {
                page.setTotal(preSize);
            }
            preTotal = preSize;
        } else {
            // 前一页
            page.setTotal(preTotal);
        }
        prePage = page.getCurrent();
        preSize = groupListMaps.size();
        page.setRecords(groupListMaps);
        Page wrapped = new EcGroupOfferingsWrapper(page).wrap();
        return LayuiPageFactory.createPageInfo(wrapped);
    }

    /**
     * 调用api接口 获取 群组语音白名单列表.
     *
     * @param transId
     * @param accountId 集团id
     * @param groupId 群组id
     * @param msisdn 卡号
     * @return 返回
     * @author cmcc-iot-api
     * @date 20200119 14:00:30
     */
    public LayuiPageInfo getGroupVoiceWhiteList(String transId, String accountId, String groupId, String msisdn) throws IOException {
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.warn("[{}] getGroupVoiceWhiteList error, accountId or groupId is null.", transId);
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11048);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_VOICE_WHITELIST);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.QUERY_GROUP_VOICE_WHITELIST);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query GroupVoiceWhiteList result string is {}.", transId, responseStr);
        ResponseDto<EcGroupVoiceWhiteDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<EcGroupVoiceWhiteDTO>>() {});
        code = result.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query GroupVoiceWhiteList error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<EcGroupVoiceWhiteDTO> ecGroupVoiceWhiteDTOList = result.getResult();
        if (ToolUtil.isEmpty(ecGroupVoiceWhiteDTOList)) {
            log.warn("[{}] query GroupVoiceWhiteList end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        List<EcGroupVoiceWhiteInfo> ecGroupVoiceWhiteInfoList = ecGroupVoiceWhiteDTOList.get(0).getGroupVoiceWhiteList();
        Page page = LayuiPageFactory.defaultPage();
        page.setTotal(Long.valueOf(ecGroupVoiceWhiteDTOList.get(0).getTotalCount()));
        if (ToolUtil.isNotEmpty(msisdn)){
            Iterator<EcGroupVoiceWhiteInfo> iterator = ecGroupVoiceWhiteInfoList.iterator();
            while (iterator.hasNext()) {
                EcGroupVoiceWhiteInfo ecGroupMemberInfo = iterator.next();
                if (!ecGroupMemberInfo.getWhiteNumber().equals(msisdn)) {
                    iterator.remove();
                }
            }
            page.setTotal(ecGroupVoiceWhiteInfoList.size());
        }
        String groupListStr = JsonUtil.toJson(ecGroupVoiceWhiteInfoList);
        List<Map<String,Object>> groupListMaps = JsonUtil.parseJson(groupListStr, new TypeReference<List<Map<String,Object>>>(){});
        page.setRecords(groupListMaps);
        Page wrapped = new EcGroupVoiceWhiteWrapper(page).wrap();
        return LayuiPageFactory.createPageInfo(wrapped);
    }

    /**
     * 调用api接口 配置群组语音白名单.
     *
     * @param transId
     * @param ecGroupVoiceWhiteSetReqDTO 群组语音白名单设置请求对象
     * @return 返回
     * @author cmcc-iot-api
     * @date 20200119 14:36:28
     */
    public Object setGroupVoiceWhite(String transId, EcGroupVoiceWhiteSetReqDTO ecGroupVoiceWhiteSetReqDTO) throws IOException {
        String groupId = ecGroupVoiceWhiteSetReqDTO.getGroupId();
        String accountId = ecGroupVoiceWhiteSetReqDTO.getAccountId();
        if (StringUtils.isBlank(accountId) || StringUtils.isBlank(groupId)) {
            log.info("[{}] setGroupVoiceWhite error, accountId or groupId is null.", transId);
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        // 封装调用api接口的参数
        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_GROUPID, groupId);
        parameterMap.put(Constants.REQUEST_PARAM_OPERTYPE, ecGroupVoiceWhiteSetReqDTO.getOperType());
        parameterMap.put(Constants.REQUEST_PARAM_WHITENUMBER, ecGroupVoiceWhiteSetReqDTO.getMsisdn());
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId, parameterMap, UrlConstants.CONFIG_GROUP_VOICE_WHITELIST);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return getResponseData(tokenResultDTO.getCode());
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of setGroupVoiceWhite is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, UrlConstants.CONFIG_GROUP_VOICE_WHITELIST);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                return getResponseData(tokenResultDTO.getCode());
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] set GroupVoice White result string is {}.", transId, responseStr);
        ResponseDto result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto>() {});
        code = result.getStatus();
        if (ErrorCode.SUCCESS.getCode().equals(code)) {
            return ResponseData.success();
        } else {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] set GroupVoice White error,error message is {}.", transId, result.getMessage());
            ResponseData responseData = new ResponseData();
            responseData.setCode(Integer.valueOf(code));
            responseData.setMessage(result.getMessage());
            return responseData;
        }
    }

    /**
     * 获取token，调用API接口
     *
     * @param tokenValid true表示使用已经初始化了的token值，false表示使用重新生成的token值
     * @param accountId 集团id
     * @param transId
     * @param parameterMap  调用api接口的参数
     * @param url 调用API接口的请求路径
     * @return 返回 API接口响应结果（或者获取token失败的原因）
     * @throws IOException
     * @author cmcc-iot-api
     * @date 20200107 09:16:37
     */
    private ResultDTO doRequest(boolean tokenValid, String accountId, String transId, Map<String, String> parameterMap, String url) throws IOException {
        // 根据 accountId 获取 token
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        // 如果token获取失败，则返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }
        // token获取成功，则调用api接口，返回调用结果
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, url);
        log.info("[{}] do request url is {}.", transId, methodUrl);
        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }

    /**
     * 根据错误码组装返回页面信息
     * @param code 错误码
     * @return
     */
    private ResponseData getResponseData(String code) {
        ErrorCode errorCode = ErrorCode.getByCode(code);
        ResponseData responseData = new ResponseData();
        responseData.setCode(Integer.valueOf(errorCode.getCode()));
        responseData.setMessage(errorCode.getMsg());
        return responseData;
    }
}
